<template>
  <div class="manage-page">
    <!-- 工具栏 -->
    <el-button link icon="plus" style="margin-left: 10px" @click="onCreate">新建</el-button>
    <!-- 菜单列表 -->
    <el-table :data="tableData" :tree-props="treeProps" row-key="id" default-expand-all>
      <el-table-column type="selection" width="55" fixed="left" />
      <el-table-column label="序号" min-width="100" fixed="left">
        <template #default="scope">
          {{ scope.row._index }}
        </template>
      </el-table-column>
      <el-table-column prop="title" label="菜单名称" width="150" />
      <el-table-column prop="icon" label="菜单图标" width="80">
        <template #default="scope">
          <el-icon v-if="isElIcon(scope.row.icon)">
            <component :is="scope.row.icon.replace('el-icon-', '')" />
          </el-icon>
          <div v-else :class="`i-svg:${scope.row.icon}`" />
        </template>
      </el-table-column>
      <el-table-column prop="type" label="菜单类型" width="80">
        <template #default="scope">
          <span>{{ scope.row.type === "page" ? "页面" : "目录" }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="order" label="菜单排序" width="80" />
      <el-table-column prop="hidden" label="隐藏菜单">
        <template #default="scope">
          <span>{{ scope.row.hidden ? "是" : "否" }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="name" label="路由名称" width="150" />
      <el-table-column prop="path" label="路由地址" />
      <el-table-column prop="component" label="组件路径">
        <template #default="scope">
          <span v-if="scope.row.type === 'page'">@src/views/{{ scope.row.component }}.vue</span>
        </template>
      </el-table-column>
      <el-table-column prop="keepAlive" label="缓存路由" width="80">
        <template #default="scope">
          <span>{{ scope.row.keepAlive ? "是" : "否" }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="alwaysShow" label="始终显示" width="80">
        <template #default="scope">
          <span>{{ scope.row.alwaysShow ? "是" : "否" }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="query" label="路由参数" />
      <el-table-column label="操作" min-width="120" fixed="right">
        <template #default="scope">
          <el-button link icon="Edit" title="编辑" @click="onEdit(scope.row)" />
          <el-button
            v-if="scope.row.type === 'dir'"
            link
            icon="Plus"
            title="添加"
            @click="onAdd(scope.row)"
          />
          <el-button
            v-if="!scope.row.children || scope.row.children.length === 0"
            link
            icon="Delete"
            title="删除"
            style="color: red"
            @click="onRemove(scope.row)"
          />
        </template>
      </el-table-column>
    </el-table>
    <!-- 新建/编辑菜单 -->
    <el-dialog v-model="dialogTableVisible" :title="dialogTitle" draggable width="600px">
      <el-form
        ref="formRef"
        :model="form"
        :rules="formRules"
        status-icon
        label-position="right"
        label-width="120px"
        label-suffix="："
      >
        <el-form-item label="父级菜单" prop="parentId">
          <el-cascader
            v-model="form.parentId"
            :props="{ label: 'title', value: 'id' }"
            :options="menuDirs"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="菜单名称" prop="title">
          <el-input v-model="form.title" autocomplete="off" />
        </el-form-item>
        <el-form-item label="菜单图标" prop="icon">
          <IconSelect v-model="form.icon" placeholder="请选择菜单图标" />
        </el-form-item>
        <el-form-item label="菜单类型" prop="type">
          <el-radio-group v-model="form.type">
            <el-radio value="page">页面</el-radio>
            <el-radio value="dir">目录</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单排序" prop="order">
          <el-input-number v-model="form.order" :min="1" :max="10" />
        </el-form-item>
        <el-form-item label="隐藏菜单" prop="hidden">
          <el-switch v-model="form.hidden" active-text="隐藏" inactive-text="不隐藏" />
        </el-form-item>
        <el-form-item label="路由名称" prop="name">
          <el-input v-model="form.name" autocomplete="off" />
        </el-form-item>
        <el-form-item label="路由地址" prop="path">
          <el-input v-model="form.path" autocomplete="off" />
        </el-form-item>
        <el-form-item label="组件路径" prop="component">
          <el-input v-model="form.component" autocomplete="off">
            <template #prepend>@src/views/</template>
            <template #append>.vue</template>
          </el-input>
        </el-form-item>
        <el-form-item label="缓存路由" prop="keepAlive">
          <el-switch v-model="form.keepAlive" active-text="缓存" inactive-text="不缓存" />
        </el-form-item>
        <el-form-item label="始终显示" prop="alwaysShow">
          <el-switch v-model="form.alwaysShow" active-text="显示" inactive-text="不显示" />
        </el-form-item>
        <el-form-item label="面包屑导航" prop="breadcrumb">
          <el-switch v-model="form.breadcrumb" active-text="显示" inactive-text="不显示" />
        </el-form-item>
        <el-form-item label="路由参数" prop="query">
          <el-input v-model="form.query" autocomplete="off" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="onClose">取消</el-button>
          <el-button type="primary" @click="onSubmit">提交</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import MenuAPI, { MenuForm } from "@/api/system/menu.api";
import { useTemplateRef } from "vue";
import { ElForm } from "element-plus";

defineOptions({
  name: "Menu",
  inheritAttrs: false,
});

const treeProps = reactive({
  checkStrictly: false,
});
const tableData = ref();

const loading = ref(false);
onBeforeMount(() => {
  handleQuery();
});

function isElIcon(icon: string): boolean {
  return (icon || "").startsWith("el-icon");
}

function setTreeIndex(data: any[], parentIndex = "") {
  data.forEach((item, i) => {
    item._index = parentIndex ? `${parentIndex}.${i + 1}` : `${i + 1}`;
    if ((item.children || []).length > 0) {
      setTreeIndex(item.children, item._index);
    }
  });
}

function handleQuery() {
  loading.value = true;
  MenuAPI.getList().then((data) => {
    setTreeIndex(data);
    tableData.value = data;
    loading.value = false;
  });
}

const dialogTableVisible = ref(false);
const dialogTitle = ref("");
const form = ref<MenuForm>({});
const formRules = reactive({
  title: [{ required: true }],
});
const menuDirs = ref();
const formRef = useTemplateRef<InstanceType<typeof ElForm> | null>("formRef");

function getMenuDirs() {
  MenuAPI.getMenuDirTree().then((data) => {
    menuDirs.value = data;
  });
}

function onCreate() {
  dialogTitle.value = "新建菜单";
  dialogTableVisible.value = true;
  form.value = new MenuForm();
  getMenuDirs();
}

function onAdd(row: MenuForm) {
  dialogTitle.value = "添加子菜单";
  const length = (row.children || []).length;
  form.value = new MenuForm({
    parentId: row.id,
    order: length > 0 ? length + 1 : 1,
  });
  dialogTableVisible.value = true;
  getMenuDirs();
}

function onEdit(row: MenuForm) {
  dialogTitle.value = "编辑菜单";
  form.value = { ...row };
  dialogTableVisible.value = true;
  getMenuDirs();
}

function onClose() {
  form.value = {};
  dialogTableVisible.value = false;
  handleQuery();
}

function onRemove(row: MenuForm) {
  ElMessageBox.confirm(`确认要删除数据 "${row.title}"？`, "提示", {
    confirmButtonText: "删除",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    MenuAPI.deleteById(row.id as number).finally(() => {
      handleQuery();
    });
  });
}

async function onSubmit() {
  if (!formRef.value) return;
  await formRef.value.validate();
  loading.value = true;
  if (form.value.id) {
    await MenuAPI.update(form.value);
  } else {
    await MenuAPI.create(form.value);
  }
  onClose();
}
</script>
